﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using System.Windows.Media;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using Styx;
using Styx.Helpers;
using Styx.Common;
using Styx.CommonBot.POI;
using Styx.CommonBot;
using Styx.CommonBot.Routines;
using Styx.Pathing;
using Styx.WoWInternals;
using Styx.WoWInternals.WoWObjects;
using Styx.TreeSharp;
using Action = Styx.TreeSharp.Action;

namespace FeralKitty
{
    public partial class Classname : CombatRoutine
    {

        public override sealed string Name { get { return "Feral + Guardian Druid by Pasterke"; } }

        public override WoWClass Class { get { return WoWClass.Druid; } }

        private static LocalPlayer Me { get { return StyxWoW.Me; } }

        private Composite _Combat, _preCombatBuffs, _CombatBuffs;
        public override Composite CombatBehavior { get { using (StyxWoW.Memory.AcquireFrame()) return _Combat; } }
        public override Composite PreCombatBuffBehavior { get { using (StyxWoW.Memory.AcquireFrame()) return _preCombatBuffs; } }
        public override Composite CombatBuffBehavior { get { using (StyxWoW.Memory.AcquireFrame()) return _CombatBuffs; } }
        WoWUnit myFocusTarget { get { return Me.FocusedUnit; } }
        public float range 
        {
            get
            {
                if (Me.CurrentTarget.IsPlayer)
                {
                    return 3.5f;
                }
                return 5;
            }
        
        }

        public override bool WantButton { get { return true; } }

        public override void OnButtonPress()
        {
            Form1 ConfigForm = new Form1();
            ConfigForm.ShowDialog();
        }

        public override void Initialize()
        {
            _Combat = createCombat();
            _preCombatBuffs = createPreCombatBuffs();
            _CombatBuffs = createCombatBuffs();
            Updater.CheckForUpdate();
            Lua.Events.AttachEvent("MODIFIER_STATE_CHANGED", HandleModifierStateChanged);
        }

        public static Stopwatch fightTimer = new Stopwatch();

        public bool RemoveDeadTargets = true;

        public bool SwitchToBearForm = false;

        public override void Pulse()
        {
            try
            {
                /*if (Me.Combat && Me.CurrentTarget.IsFriendly)
                {
                    Me.ClearTarget();
                    LogMsg("Friendly Target removed because I'm in Combat (" + Me.CurrentTarget.Name + ")", 1);
                    return;
                }*/
                if (Me.Combat && RemoveDeadTargets && Me.CurrentTarget.IsDead)
                {
                    Me.ClearTarget();
                    return;
                }
            }
            catch { }
        }

        #region CC_Begin


        public override bool NeedRest
        {
            get
            {
                if (UseSpells)
                {
                    if (Me.HealthPercent > FeralKittySettings.AllPrefs.HealingTouchOOC
                        && Me.HealthPercent <= FeralKittySettings.AllPrefs.RejuvenationOOC
                        && !Me.GroupInfo.IsInRaid
                        && !Me.IsInInstance
                        && !Me.Mounted)
                    {
                        return true;
                    }
                    if (Me.HealthPercent <= FeralKittySettings.AllPrefs.HealingTouchOOC
                        && Me.HealthPercent > FeralKittySettings.AllPrefs.EatDrinkOOC
                        && !Me.GroupInfo.IsInRaid
                        && !Me.IsInInstance
                        && !Me.Mounted)
                    {
                        return true;
                    }
                    if (Me.HealthPercent <= FeralKittySettings.AllPrefs.EatDrinkOOC
                        && !Me.GroupInfo.IsInRaid
                        && !Me.IsInInstance
                        && !Me.Mounted
                        && !Me.IsSwimming)
                    {
                        return true;
                    }
                }
                return false;
            }
        }

        public override void Rest()
        {
            if (UseSpells)
            {
                if (SpellManager.HasSpell(Rejuvenation)
                    && !Me.HasAura("Food")
                    && !Me.HasAura("Drink")
                    && !Me.HasAura("First Aid")
                    && Me.HealthPercent <= FeralKittySettings.AllPrefs.RejuvenationOOC
                    && Me.HealthPercent >= FeralKittySettings.AllPrefs.HealingTouchOOC
                    && !Me.HasAura(Rejuvenation)
                    && !Me.Mounted
                    && !Me.IsGhost)
                {
                    CastBuff(Rejuvenation, 2);
                }
                if (SpellManager.HasSpell(HealingTouch)
                    && !Me.HasAura("Food")
                    && !Me.HasAura("Drink")
                    && !Me.HasAura("First Aid")
                    && Me.HealthPercent < FeralKittySettings.AllPrefs.HealingTouchOOC
                    && Me.HealthPercent > FeralKittySettings.AllPrefs.EatDrinkOOC
                    && !Me.Mounted
                    && !Me.IsGhost)
                {
                    CastBuff(HealingTouch, 2);
                }
                if (((!SpellManager.HasSpell(HealingTouch) && Me.HealthPercent <= FeralKittySettings.AllPrefs.HealingTouchOOC)
                    || Me.HealthPercent < FeralKittySettings.AllPrefs.EatDrinkOOC)
                    && !Me.HasAura("First Aid")
                    && !Me.Mounted
                    && !Me.IsSwimming
                    && !Me.IsGhost)
                {
                    Styx.CommonBot.Rest.Feed();
                }
            }
        }

        #endregion

        #region Pull

        public override void Pull()
        {
            if (gotTarget
                && (Me.Specialization == WoWSpec.DruidFeral
                || (Me.Level > 6 && Me.Level < 10))
                && UseForm == "Cat")
            {
                CatPull();
            }
            if (gotTarget
                && (Me.Specialization == WoWSpec.DruidGuardian
                || UseForm == "Bear"))
            {
                BearPull();
            }

        }


        #endregion

        #region Pull Buffs

        public override bool NeedPullBuffs
        {
            get
            { 
                
                if (gotTarget
                    && (Me.Specialization == WoWSpec.DruidFeral || (Me.Level < 10 && SpellManager.HasSpell("Cat Form")))
                    && SpellManager.HasSpell(Prowl)
                    && FeralKittySettings.AllPrefs.useProwl
                    && !spellOnCooldown("Prowl")
                    && !buffExists("Prowl", Me)
                    && !Me.Mounted)
                {
                    if (SpellManager.CanCast("Prowl"))
                    {
                        SpellManager.Cast("Prowl");
                        LogMsg("Prowl", 1);
                    }
                }
                return false;
            }
        }

        public override void PullBuff() { }

        #endregion

         
        #region precombatbuffs
        public Composite createPreCombatBuffs()
        {
            return new PrioritySelector(
                CastBuff("Mark of the Wild", ret => !buffExists("Mark of the Wild", Me)
                    && !Me.GroupInfo.IsInRaid
                    && !Me.IsInInstance
                    && !Me.GroupInfo.IsInParty),
                new Action(ret => { AlchemistFlask(); return RunStatus.Failure; }),
                CastBuff("Aquatic Form", ret => !Me.Combat
                    && !Me.IsGhost
                    && !Me.HasAura("Prowl")
                    && Me.IsSwimming
                    && !Me.Mounted
                    && Me.Shapeshift != ShapeshiftForm.Aqua)
                );
        }
        #endregion precombatbuffs

        #region CombatBuffs
        public Composite createCombatBuffs()
        {
            return new PrioritySelector(
                useCatForm(),
                useBearForm(),

                new Action(ret => { AlchemistFlask(); return RunStatus.Failure; }),
                new Action(ret => { myFlask(); return RunStatus.Failure; }),
                new Action(ret => { HealthStone(); return RunStatus.Failure; }),

                Cast("Cenarion Ward", ret => gotTarget
                    && !spellOnCooldown("Cenarion Ward")
                    && Me.HealthPercent <= FeralKittySettings.AllPrefs.CenarionWard
                    && !Me.Mounted),

                Cast("Barkskin", ret => gotTarget
                    && !spellOnCooldown("Barkskin")
                    && Me.HealthPercent <= FeralKittySettings.AllPrefs.Barskin
                    && !Me.Mounted),

                Cast("Survival Instincts", ret => gotTarget
                    && !spellOnCooldown("Survival Instincts")
                    && Me.HealthPercent <= FeralKittySettings.AllPrefs.SurvivalInstincts
                    && !Me.Mounted),

                Cast("Tiger's Fury", ret => gotTarget
                    && LastSpell != "Tiger's Fury"
                    && !buffExists("Lifeblood", Me)
                    && !HaveHasteBuff
                    && Me.EnergyPercent <= 25
                    && Me.CurrentTarget.IsWithinMeleeRange
                    && !Me.Mounted),

                Cast("Lifeblood", ret => gotTarget
                    && LastSpell != "Lifeblood"
                    && ((FeralKittySettings.AllPrefs.Lifeblood == 2 && IsBoss)
                    || FeralKittySettings.AllPrefs.Lifeblood == 1)
                    && SpellManager.HasSpell("Lifeblood")
                    && !buffExists("Tiger's Fury", Me)
                    && !HaveHasteBuff
                    && Me.EnergyPercent <= 25
                    && Me.CurrentTarget.IsWithinMeleeRange
                    && !Me.Mounted),

                Cast("Berserk", ret => gotTarget
                    && LastSpell != "Berserk"
                    && !spellOnCooldown("Berserk")
                    && !HaveHasteBuff
                    && ((FeralKittySettings.AllPrefs.Berserk == 1 && IsBoss)
                    || FeralKittySettings.AllPrefs.Berserk == 2)
                    && Me.CurrentTarget.IsWithinMeleeRange
                    && targetExistence(Me.CurrentTarget) > 5
                    && !Me.Mounted),

                Cast("Incarnation", ret => gotTarget
                    && !spellOnCooldown("Incarnation")
                    && buffExists("Berserk", Me)
                    && Me.CurrentTarget.IsWithinMeleeRange
                    && !Me.Mounted),

                Cast("Berserking", ret => gotTarget
                    && SpellManager.HasSpell("Berserking")
                    && LastSpell != "Berserking"
                    && !spellOnCooldown("Berserking")
                    && !HaveHasteBuff
                    && ((FeralKittySettings.AllPrefs.Berserking == 1
                    && IsBoss)
                    || FeralKittySettings.AllPrefs.Berserking == 2)
                    && Me.CurrentTarget.IsWithinMeleeRange
                    && targetExistence(Me.CurrentTarget) > 10
                    && !Me.Mounted),
                Cast("Bone Shield", ret => gotTarget && !buffExists("Bone Shield", Me) && !spellOnCooldown("Bone Shield") && Me.Specialization == WoWSpec.DruidGuardian),

                new Action(ret => { UseTrinket1(); return RunStatus.Failure; }),
                new Action(ret => { UseTrinket2(); return RunStatus.Failure; }),
                new Action(ret => { UseEngiGloves(); return RunStatus.Failure; }),
                new Action(ret => { myPotion(); return RunStatus.Failure; })
                );
        }
        #endregion CombatBuffs
        #region combat
        public Composite createCombat()
        {
            return new PrioritySelector(
                new Decorator(ret => Paused, PauseCr()),
                new Decorator(ret => gotTarget && Me.Specialization == WoWSpec.DruidGuardian && !Me.Mounted, createGuardianRotation()),
                new Decorator(ret => !Me.GotTarget && Me.Combat && !FeralKittySettings.AllPrefs.DisableTargetting && !Me.Mounted, GetNewTarget()),
                new Decorator(ret => gotTarget && Me.Specialization == WoWSpec.DruidFeral && Me.Shapeshift == ShapeshiftForm.Bear && !Me.Mounted, createBearRotation()),
                new Decorator(ret => gotTarget && Me.Shapeshift != ShapeshiftForm.Bear && addCount >= FeralKittySettings.AllPrefs.useCatAoe && !Me.Mounted, createCatAoeRotation()),
                new Decorator(ret => gotTarget && Me.Shapeshift == ShapeshiftForm.Cat && !Me.Mounted, createCatRotation())
                );
        }

        public Composite createCatRotation()
        {
            return new PrioritySelector(
                Cast("Moonfire", ret => gotTarget && !debuffExists("Moonfire",Me.CurrentTarget) && Me.Level < 6),
                Cast("Wrath", ret => gotTarget && Me.Level < 6),

                useCatForm(),
                checkRange(),
                MeMoving(),
                Facing(),

                CastFocus("Cyclone", ret => FeralKittySettings.AllPrefs.Cyclone && !debuffExists("Cyclone", myFocusTarget)),

                Cast("Healing Touch", ret => gotTarget
                    && buffExists("Predatory Swiftness", Me)
                    && buffTimeLeft("Predatory Swiftness", Me) > 2000
                    && Me.CurrentTarget.IsWithinMeleeRange),
                Cast("Feral Spirit", ret => gotTarget
                    && SpellManager.HasSpell("Feral Spirit")
                    && !spellOnCooldown("Feral Spirit")
                    && (FeralKittySettings.AllPrefs.FeralSpirit == 1
                    || (FeralKittySettings.AllPrefs.FeralSpirit == 2 && IsBoss))),
                Cast("Thrash", ret => gotTarget
                    && LastSpell != "Thrash"
                    && ((!debuffExists("Thrash", Me.CurrentTarget) && buffExists("Clearcasting", Me))
                    || (!debuffExists("Thrash", Me.CurrentTarget) && addCount > 1 && (Me.EnergyPercent >= 50 || buffExists("Clearcasting", Me))))
                    && Me.CurrentTarget.IsWithinMeleeRange),
                 Cast("Ferocious Bite", ret => gotTarget
                    && debuffExists("Rip", Me.CurrentTarget)
                    && Me.ComboPoints >= myComboPoints
                    && Me.EnergyPercent >= 25
                    && Me.CurrentTarget.IsWithinMeleeRange),
                Cast("Ferocious Bite", ret => gotTarget
                    && !SpellManager.HasSpell("Rip")
                    && Me.ComboPoints >= 3
                    && Me.CurrentTarget.IsWithinMeleeRange),
                 Cast("Savage Roar", ret => gotTarget
                    && ((Me.ComboPoints == 0 && HaveGlyph("Savagery") && !debuffExists("Savage Roar", Me))
                    || (Me.ComboPoints > 0 && !debuffExists("Savage Roar", Me)))
                    && Me.EnergyPercent >= 25),
                Cast(FF, ret => gotTarget
                    && !debuffExists(FF, Me.CurrentTarget)
                    && !spellOnCooldown(FF)
                    && Me.CurrentTarget.IsWithinMeleeRange),
                Cast("Rake", ret => gotTarget
                    && !debuffExists("Rake", Me.CurrentTarget)
                    && Me.EnergyPercent >= 35
                    && Me.CurrentTarget.IsWithinMeleeRange),
                Cast("Ravage", ret => gotTarget
                    && buffExists("Incarnation: King of the Jungle", Me)
                    && Me.EnergyPercent >= 45
                    && Me.CurrentTarget.IsWithinMeleeRange),
                Cast("Mighty Bash", ret => gotTarget
                    && SpellManager.HasSpell("Mighty Bash")
                    && !spellOnCooldown("Mighty Bash")
                    && FeralKittySettings.AllPrefs.MightyBash
                    && Me.CurrentTarget.IsCasting
                    && Me.CanInterruptCurrentSpellCast
                    && Me.CurrentTarget.IsWithinMeleeRange),
                Cast("Skull Bash", ret => gotTarget
                    && !spellOnCooldown("Skull Bash")
                    && FeralKittySettings.AllPrefs.SkullBash
                    && Me.CurrentTarget.IsCasting
                    && Me.CanInterruptCurrentSpellCast
                    && Me.CurrentTarget.IsWithinMeleeRange),
                Cast("Rip", ret => gotTarget
                    && !debuffExists("Rip", Me.CurrentTarget)
                    && Me.EnergyPercent >= 30
                    && Me.ComboPoints >= myComboPoints
                    && Me.CurrentTarget.IsWithinMeleeRange),
                Cast("Shred", ret => gotTarget
                    && FeralKittySettings.AllPrefs.shred
                    && (debuffExists("Thrash", Me.CurrentTarget)
                    || debuffExists("Rake", Me.CurrentTarget))
                    && Me.IsSafelyBehind(Me.CurrentTarget)
                    && Me.EnergyPercent >= 40),
                Cast("Mangle", ret => gotTarget
                    && Me.EnergyPercent >= 35
                    && Me.CurrentTarget.IsWithinMeleeRange)
                );
        }
        public Composite createBearRotation()
        {
            return new PrioritySelector(
                useBearForm(),
                checkRange(),
                new Decorator(ret => gotTarget && !FeralKittySettings.AllPrefs.DisableMovement && !Me.CurrentTarget.InLineOfSight, MoveInLingOfSight()),
                MeMoving(),
                Facing(),
                Cast("Faerie Swarm", ret => gotTarget
                    && !debuffExists("Faerie Swarm", Me.CurrentTarget)
                    && !spellOnCooldown("Faerie Swarm")
                    && Me.CurrentTarget.IsWithinMeleeRange),
                Cast("Mighty Bash", ret => gotTarget
                    && SpellManager.HasSpell("Mighty Bash")
                    && !spellOnCooldown("Mighty Bash")
                    && FeralKittySettings.AllPrefs.MightyBashBear
                    && Me.CurrentTarget.IsCasting
                    && Me.CanInterruptCurrentSpellCast
                    && Me.CurrentTarget.IsWithinMeleeRange),
                Cast("Skull Bash", ret => gotTarget
                    && !spellOnCooldown("Skull Bash")
                    && FeralKittySettings.AllPrefs.SkullBashBear
                    && Me.CurrentTarget.IsCasting
                    && Me.CanInterruptCurrentSpellCast
                    && Me.CurrentTarget.IsWithinMeleeRange),
                Cast("Thrash", ret => gotTarget
                    && !debuffExists("Thrash", Me.CurrentTarget)
                    && !spellOnCooldown("Thrash")
                    && Me.CurrentTarget.IsWithinMeleeRange),
                Cast("Swipe", ret => gotTarget
                    && (!spellOnCooldown("Swipe")
                    || (Me.RagePercent >= 15 && !spellOnCooldown("Swipe")))
                    && Me.CurrentTarget.IsWithinMeleeRange),
                Cast("Maul", ret => gotTarget 
                    && !spellOnCooldown("Maul") 
                    && Me.RagePercent >= 60
                    && Me.CurrentTarget.IsWithinMeleeRange),
                Cast("Lacerate", ret => gotTarget && !spellOnCooldown("Lacerate"))
                );
        }
        public Composite createCatAoeRotation()
        {
            return new PrioritySelector(
                useCatForm(),
                checkRange(),
                new Decorator(ret => gotTarget && !FeralKittySettings.AllPrefs.DisableMovement && !Me.CurrentTarget.InLineOfSight, MoveInLingOfSight()),
                MeMoving(),
                Facing(),
                Cast("Savage Roar", ret => gotTarget
                    && ((Me.ComboPoints == 0 && HaveGlyph("Sacagery") && !buffExists("Savage Roar", Me))
                    || (Me.ComboPoints > 0 && !buffExists("Savage Roar", Me)))
                    && Me.EnergyPercent >= 25),
                Cast("Thrash", ret => gotTarget
                    && LastSpell != "Thrash"
                    && !debuffExists("Thrash", Me.CurrentTarget)
                    && (Me.EnergyPercent >= 50 || buffExists("Clearcasting", Me))
                    && Me.CurrentTarget.IsWithinMeleeRange),
                Cast("Swipe", ret => gotTarget
                    && Me.EnergyPercent >= 45
                    && Me.CurrentTarget.IsWithinMeleeRange)
                );
        }
        public Composite createGuardianRotation()
        {
            return new PrioritySelector(
                useBearForm(),
                checkRangeBear(),
                new Decorator(ret => gotTarget && !Me.CurrentTarget.InLineOfSight, MoveInLingOfSight()),
                MeMoving(),
                FacingBear(),
                
                Cast("Mighty Bash", ret => gotTarget 
                    && FeralKittySettings.AllPrefs.MightyBashBear 
                    && !spellOnCooldown("Mighty Bash") 
                    && Me.CurrentTarget.IsCasting 
                    && Me.CanInterruptCurrentSpellCast),
                Cast("Skull Bash", ret => gotTarget 
                    && FeralKittySettings.AllPrefs.SkullBashBear 
                    && !spellOnCooldown("Skull Bash") 
                    && Me.CurrentTarget.IsCasting 
                    && Me.CanInterruptCurrentSpellCast),
                Cast(FF, ret => gotTarget && !debuffExists(FF, Me.CurrentTarget) && !spellOnCooldown(FF)),
                Cast("Maul", ret => gotTarget && Me.RagePercent >= 92 || (buffExists("Tooth and Claw", Me) && Me.RagePercent >= 30)),
                Cast("Savage Defense", ret => gotTarget && buffExists("Tooth and Claw", Me) && Me.RagePercent >= 60),
                Cast("Mangle", ret => gotTarget && !spellOnCooldown("Mangle")),
                Cast("Thrash", ret => gotTarget && !spellOnCooldown("Thrash") && addCount == 1 && !debuffExists("Thrash", Me.CurrentTarget)),
                Cast("Thrash", ret => gotTarget && !spellOnCooldown("Thrash") && addCount > 1),
                Cast("Swipe", ret => gotTarget && addCount > 1 && Me.RagePercent >= 15),
                Cast("Lacerate", ret => gotTarget && !spellOnCooldown("Lacerate"))

                );
        }
        public Composite Facing()
        {
            return new Decorator(ret => !Me.IsSafelyFacing(Me.CurrentTarget) && !FeralKittySettings.AllPrefs.DisableFacing,
                new Action(ret => Me.CurrentTarget.Face())
            );
        }
        public Composite FacingBear()
        {
            return new Decorator(ret => !Me.IsSafelyFacing(Me.CurrentTarget) && !FeralKittySettings.AllPrefs.DisableFacingBear,
                new Action(ret => Me.CurrentTarget.Face())
            );
        }
        public Composite checkRange()
        {
            return new Decorator(ret => !FeralKittySettings.AllPrefs.DisableMovement && Me.CurrentTarget.Distance > range,
                new Action(ret => 
                {
                    Navigator.MoveTo(StyxWoW.Me.CurrentTarget.Location);
                }));
        }
        public Composite checkRangeBear()
        {
            return new Decorator(ret => !FeralKittySettings.AllPrefs.DisableMovementBear && Me.CurrentTarget.Distance > range,
                new Action(ret =>
                {
                    Navigator.MoveTo(StyxWoW.Me.CurrentTarget.Location);
                }));
        }
        public Composite MoveInLingOfSight()
        {
            return new Action(ret =>
            {
                Navigator.MoveTo(StyxWoW.Me.CurrentTarget.Location);
            });
        }
        public Composite MeMoving()
        {
            return new Decorator(ret => !FeralKittySettings.AllPrefs.DisableMovement 
                && Me.IsMoving 
                && Me.CurrentTarget.IsWithinMeleeRange 
                && Me.CurrentTarget.InLineOfSight
                && Me.CurrentTarget.Distance <= range,
                new Action(ret => Navigator.PlayerMover.MoveStop()));
        }
        #endregion combat

        public Composite PauseCr()
        {
            return new Action(ret => 
            {
                return;
            });
        }


     
    }
}